//
// Created by Zsir on 2025/8/22.
//

#include "EventLoop.h"
#include "Channel.h"
#include "EpollPoller.h"
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
#include <thread>

thread_local EventLoop *t_loopInThisThread = nullptr;

EventLoop::EventLoop()
    : looping_(false),
      quit_(false),
      callingPendingFunctors_(false),
      threadId_(std::this_thread::get_id()),
      poller_(new EpollPoller(this)),
      wakeupFd_(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC))
{

    if (wakeupFd_ < 0)
    {
        std::cerr << "创建 eventfd 失败" << std::endl;
        abort();
    }

    if (t_loopInThisThread)
    {
        std::cerr << "当前线程已存在另一个 EventLoop" << std::endl;
        abort();
    }
    t_loopInThisThread = this;

    wakeupChannel_.reset(new Channel(this, wakeupFd_));
    wakeupChannel_->setReadCallback(std::bind(&EventLoop::handleWakeup, this));
    wakeupChannel_->enableReading();
}

EventLoop::~EventLoop()
{
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();
    close(wakeupFd_);
    t_loopInThisThread = nullptr;
}

/*
 * 确保当前线程是 EventLoop 的所属线程
 * 设置标志位
 * 处理循环事件 先建立通道列表，然后调用epoll-wait,注册新的通道，和关注事件，然后处理本轮的IO事件
 * doPendingFunctors处理之前丢到工作线程里面的好事任务，防止阻塞loop
 * 优雅退出
 */
void EventLoop::loop()
{
    assertInLoopThread();
    looping_.store(true);
    quit_.store(false);
    while (!quit_.load())
    {
        EpollPoller::ChannelList active;
        poller_->poll(-1, &active);
        for (auto *ch: active) ch->handleEvent();
        doPendingFunctors();
    }
    looping_.store(false);
}

void EventLoop::quit()
{
    quit_.store(true);
    if (!isInLoopThread())
    {
        wakeup();
    }
}

void EventLoop::runInLoop(Functor cb)
{
    if (isInLoopThread())
    {
        cb();
    } else
    {
        queueInLoop(std::move(cb));
    }
}

void EventLoop::queueInLoop(Functor cb)
{
    {
        std::lock_guard<std::mutex> lock(mutex_);
        pendingFunctors_.push_back(std::move(cb));
    }

    if (!isInLoopThread() || callingPendingFunctors_.load())
    {
        wakeup();
    }
}

void EventLoop::updateChannel(Channel *channel)
{
    assertInLoopThread();
    poller_->updateChannel(channel);
}

void EventLoop::removeChannel(Channel *channel)
{
    assertInLoopThread();
    poller_->removeChannel(channel);
}

bool EventLoop::isInLoopThread() const
{
    return threadId_ == std::this_thread::get_id();
}

void EventLoop::assertInLoopThread()
{
    if (!isInLoopThread())
    {
        std::cerr << "EventLoop::assertInLoopThread - 不在事件循环所属线程中" << std::endl;
        abort();
    }
}

void EventLoop::handleWakeup()
{
    uint64_t one = 1;
    ssize_t n = read(wakeupFd_, &one, sizeof(one));
    if (n != sizeof(one))
    {
        std::cerr << "EventLoop::handleWakeup() 读取字节数异常：" << n << "（应为 8）" << std::endl;
    }
}

void EventLoop::doPendingFunctors()
{
    std::vector<Functor> functors;
    callingPendingFunctors_.store(true);

    {
        std::lock_guard<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_);
    }

    for (const auto &functor: functors)
    {
        functor();
    }

    callingPendingFunctors_.store(false);
}

void EventLoop::wakeup()
{
    uint64_t one = 1;
    ssize_t n = write(wakeupFd_, &one, sizeof(one));
    if (n != sizeof(one))
    {
        std::cerr << "EventLoop::wakeup() 写入字节数异常：" << n << "（应为 8）" << std::endl;
    }
}